﻿using System;
using System.Linq;
using System.ServiceModel;
using ExplorerService.Common.ServiceContracts;
using ExplorerService.Managers;

namespace ExplorerService.Communication
{

    public class ApplicationMonitorService : ClientSessionMonitoredService, IApplicationMonitorService
    {
        /// <summary>
        /// Callback for this session
        /// </summary>
        private IApplicationMonitorServiceCallback _callback;

        /// <summary>
        /// Starts the monitor for a client session
        /// </summary>
        /// <param name="sessionId">The ID of the client session</param>
        public void StartMonitor(Guid sessionId)
        {
            VerifySessionIdAndRegister(sessionId);
            var currentSessions = ApplicationSessionManager.Instance.Sessions.ToList();
            var callback = OperationContext.Current.GetCallbackChannel<IApplicationMonitorServiceCallback>();
            _callback = callback;
            ApplicationSessionManager.Instance.SessionStarted += ApplicationSessionStarted;
            ApplicationSessionManager.Instance.SessionEnded += ApplicationSessionEnded;
            ApplicationSessionManager.Instance.SessionLocked += SessionLocked;
            ApplicationSessionManager.Instance.SessionUnlocked += SessionUnlocked;
            foreach (var applicationSession in currentSessions)
            {
                callback.SessionStarted(applicationSession.SessionId, applicationSession.Information);
                if (applicationSession.Locked)
                {
                    callback.SessionLocked(applicationSession.SessionId, false);
                }
            }
        }

        /// <summary>
        /// Pings the service to make sure the it's still alive
        /// </summary>
        /// <returns></returns>
        public bool Ping()
        {
            return true;
        }

        void SessionUnlocked(Guid sessionId)
        {
            _callback.SessionUnlocked(sessionId);
        }

        void SessionLocked(Guid sessionId, Guid clientSessionId)
        {
            _callback.SessionLocked(sessionId, clientSessionId == SessionId);
        }

        /// <summary>
        /// Handles session end for application sessions
        /// </summary>
        /// <param name="sessionId"></param>
        void ApplicationSessionEnded(Guid sessionId)
        {
            _callback.SessionEnded(sessionId);
        }

        /// <summary>
        /// Handles session start for application sessions
        /// </summary>
        /// <param name="sessionId"></param>
        void ApplicationSessionStarted(Guid sessionId)
        {
            _callback.SessionStarted(sessionId, ApplicationSessionManager.Instance[sessionId].Information);
        }

        /// <summary>
        /// Stops the monitor and closes the service session
        /// </summary>
        public void EndMonitor()
        {
            ApplicationSessionManager.Instance.SessionStarted -= ApplicationSessionStarted;
            ApplicationSessionManager.Instance.SessionEnded -= ApplicationSessionEnded;
            ApplicationSessionManager.Instance.SessionLocked -= SessionLocked;
            ApplicationSessionManager.Instance.SessionUnlocked -= SessionUnlocked;
        }

        /// <summary>
        /// Method called to clean up service resources
        /// </summary>
        protected override void ServiceDispose()
        {
            EndMonitor();
        }
    }
}